/**

This file is part of MaCI/GIMnet.

MaCI/GIMnet is free software: you can redistribute it and/or modify it 
under the terms of the GNU Lesser General Public License as published 
by the Free Software Foundation, either version 3 of the License, or 
(at your option) any later version.

MaCI/GIMnet is distributed in the hope that it will be useful, but WITHOUT 
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 
FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public 
License for more details.

You should have received a copy of the GNU Lesser General Public 
License along with GIMnet. (See COPYING.LESSER) If not, see 
<http://www.gnu.org/licenses/>.

**/
/**
 * \file
 * \brief Linux implementation of USB driver
 * \author Matthieu Myrsky <matthieu.myrsky@tkk.fi>
 * This header contains the class declaration for the Linux USB driver abstraction.
 */
#ifndef _USB_LINUX_HPP_
#define _USB_LINUX_HPP_
#include "ownutils.h"
#include "owndebug.h"
#include <usb.h>

/** Linux USB driver interface.
 * This class is a simplified interface for Linux USB driver. It's intended
 * to be matching to the USB driver interface on windows, so we can use
 * the same code on both OSses.
 */
class CUSB_Linux {
public:
  /**
   *Constructor
   */
  CUSB_Linux();

  /**
   * Destructor
   */
  virtual ~CUSB_Linux();

  /**
   * Opens the device. 
   *
   * \see SearchForDevice
   *
   * @param[in] aDeviceToOpen     Handle to USB device to open. Get the right device
   *                              by using SearchForDevice-function
   *
   * @return                      True if succesfully opened, else false
   */
  bool Open(struct usb_device *aDeviceToOpen);

  /**
   * Closes the device
   *
   * @return       True if succesfully closed
   */
  bool Close(void);

  /**
   * Reads usb device
   *
   * @param[in] endPoint          End point number of the device
   * @param[out] aBuffer          Buffer to save the readed data. You must allocate memory
   *                              before calling this function
   * @param[in] aSize             Size of the buffer
   * @param[in] aTimeout_ms       Timeout(in ms) for this call
   *
   * @return                      number of bytes read. -1 on error.
   */
  int Read(int endPoint,char *aBuffer, unsigned int aSize, unsigned int aTimeout_ms);
 
  /**
   * Sends a control message
   *
   * @param[in] aBuffer           Message buffer
   * @param[in] aSize             Size of buffer
   * @param[in] aTimeout_ms       Timeout (in ms) for this call
   * @param[in] aRequestType      
   * @param[in] aRequest        
   * @param[in] aRequestValue    
   * @param[in] aIndex            USB message index value 
   *
   * @return  
   */
  int ControlMessage(char *aBuffer, 
                     unsigned int aSize, 
                     unsigned int aTimeout_ms,
                     int aRequestType,
                     int aRequest,
                     int aRequestValue,
                     int aIndex);
  
  /**
   * Writes to usb device
   *
   * @param[in] endPoint           End point number of the device
   * @param[out] aBuffer           Buffer to write.
   * @param[in] aSize              Size of the buffer
   * @param[in] aTimeout_ms        Timeout for this call
   *
   * @return                       number of bytes written. -1 on error.
   */
  int Write(int endPoint,char *aBuffer, unsigned int aSize, unsigned int aTimeout_ms);

  /**
   * Search for device by vendorID and deviceID
   *
   * @param[in] aVendorId          Vendor ID of the device
   * @param[in] aDeviceId          Device ID of the device
   * @param[out] devs              Handles for the USB devices found.
   *                 
   * @return                       Number of device found with these criterias
   */
  int SearchForDevice(unsigned int aVendorId,unsigned int aDeviceId,struct usb_device *devs[]);

private:
 CUSB_Linux(const CUSB_Linux &) :
   iOpen(false),
   iUsb_handle(){}

  CUSB_Linux& operator=(const CUSB_Linux &) { return *this; }
  bool iOpen;
  struct usb_dev_handle *iUsb_handle;
};

#endif
